#1 WSGI 程序起步
本文中程序的放置路径及运行方式在 Window + Apache + WSGI 配置指明。
第一WSGI程序
WSGI server检索application函数, 并传递两个参数environ, start_response。
environ 为一个字典,包含环境变量。
start_response 为一个函数, 用于返回状态信息。
一个WSGI程序要完成两件事:
其一:返回HTTP header。本例中, 状态‘200 OK‘, 表明一切正常。
其二:返回一个iterable containing, 本例中是一个list。
输出environ信息
|
|
上述代码也可以通过类来实现,类中要重载call,这样的好处是可以从其它类继承,复用代码。
|
|
#2 WSGI– Middleware
#
假定存在一个superSession模块,用于追踪用户访问行为。
上述代码创建了一个Session对象,追踪用户访问行为。将上述思想用于WSGI程序中。
可以将上述代码进行重构。
将session代码抽离放于session函数中,该函数专门用于判断用户访问行为。session函数将判断结果至于环境变量environ字典中。
exampleApplication通过environ字典获得用户访问行为。
我们称session函数为middleware,它处于server与application之间,对server传来的请求做相应的处理;它对于Server和application是透明的。
middleware的好处在于,通过middleware(本例中session函数)可以很简单的给WSGI程序添加新功能。
我们也可见将middleware包装成类,这样,我们可以通过继承,复用现有的中间件。类中要重载call。
附录: 代码语法解释
将exampleApplication传入session函数,session函数中定义了一个新的函数app,session将app返回赋给application。
实际上相当于application = app。app函数中进行相应处理(superSession),将处理好的environ在传递给exampleApplication。
#3 webob request response
###Request
Webob的Request对象,提供对WSGI environ环境变量的包装,通过webob可以很容易的读写environ字典。
environ字典内容如下:
|
|
|
|
通过Request操作上述环境变量,所得结果如下:
req.method ‘Get’
req.path_info ‘/‘
req.content_type ‘text/plain’
req.remote_user ‘None’
req.host ‘localhost:8080’
即通过req,可以很方便的读取environ环境变量,更多操作请看:http://docs.webob.org/en/latest/modules/webob.html
Response包含了所有响应WSGI Server需要的变量。
使用webob改写之前的Hello World程序。j将上述代码粘贴到eclipse中,运行。
4 Webob WSGI 装饰器wsgify装饰器将一个普通函数转变成WSGI应用程序。
class webob.dec.wsgify(func=None, RequestClass=None, args=(), kwargs=None, middleware_wraps=None)
小示例
其中,参数req为一个Request实例,可以通过req读取相应环境变量。
而且,我们可以定制装饰器
如何是本机访问,则输出’hi‘,否则不允许
5 Routes 起步
1.2 行创建一个mapper
行注册一条路由, 路由名称为’spch’, 路径为’/blog’, controller为main,
action为index
可以这样认为,匹配到此条路由的请求交由controller处理,请求预调用的
函数为index创建好路由条目后,即可以进行匹配,调用match方法,匹配路径’blog’
- 输出匹配结果1234map.connect(None, "/error/{action}/{id}", controller="error")result = map.match('/error/index/2')print result{'action': u'index', 'controller': u'error', 'id': u'2'}
1.注册了一条无名路由,并且action从匹配路由中获得
同样,我们可以省掉None
map.connect(“/error/{action}/{id}”, controller=”error”)
上述语句同样注册了一条无名路由。
Conditions
Conditions用于限制进行路由匹配,比如method
|
|
\d表示匹配1位数字,\d+表示匹配多位
windows|mac 表示只匹配windows或者mac
可以将上述写成
Format extensions
通过{.format}来指定匹配格式
|
|
注意:{id:\d+}, 如果没有\d+, print map.match(‘/entries/2.mp4’)将输出 {‘id’: u’2.mp4’, ‘format’: None}是可以成功的。
有了\d+后,由于没有匹配format,同时\d+要求只匹配数字,所有2.mp4匹配失败
6 Routes Resource当路由条目过多时,需要一条一条注册,过于麻烦,此时可以通过resource route简化
上述路由条目可以使用这一条语句代替。
两个参数,一个指定单数,为member路由名字;一个指定复数,为collection路由名字。
函数原型:resource(member_name, collection_name, **kwargs)
这里有必要说一下member 路由与 collection路由。
上述的路由模型
- 有的路由有id, 指向一个具体的对象
- 有的路由没有id, 指向全体对象
- 有的路由(index/create, show/update/delete)有相同的URL,但是HTTP method不同
- 有的路由(show/edit)HTTP method和前缀相同,仅后缀不同
一个member路由指定具体实例,也就是说它们有id。而一个collection路由,
没有指定的实例,即没有给定id
综上:member路由操作一个单独的实例,而collection操作全体实例。
另一个函数collection也可以完成上述功能。
函数原型:collection(collection_name, resource_name, path_prefix=None, member_prefix=’/{id}’, controller=None, collection_actions=[‘index’, ‘create’, ‘new’],member_actions=[‘show’, ‘update’,
‘delete’, ‘edit’], member_options=None, **kwargs)
用法:
map.collection(‘entries’, ‘entry’)
7 Routes RoutesMiddlewareRoutesMiddleware将请求应声到相应WSGI程序,它将路由匹配结果存到environ环境变量中去。
map调用match匹配URL,并设置WSGI环境变量
route为匹配到的路由,url为一个URLGenerator对象,match为匹配所得条目。
app为一个RoutesMiddleware对象,内部重载call(def call(self, environ, start_response))仍为一个wsgi应用。
wsgi_app为一个wsgi程序,RoutesMiddleware将环境变量(environ)设置好后,调用wsgi_app进行后续处理。
下面是一个实际的输出:
8 WSGI Webob Routes 实例1.下载库文件
webob库:http://download.csdn.net/detail/spch2008/5497755
routes库:http://download.csdn.net/detail/spch2008/5497757
repoze库:http://download.csdn.net/detail/spch2008/5499231
- 组织代码
- 代码
'''
Created on 2013-6-1
@author: spch2008
'''
from wsgiref.simple_server import make_server
import routes.middleware
import webob.dec
import webob.exc
class Controller:
def __call__(self, req):
return webob.Response("Hello World!")
class Router(object):
def __init__(self):
self._mapper = routes.Mapper()
self._mapper.connect('/spch',
controller=Controller(),
action='index',
conditions={'method': ['GET']})
self._router = routes.middleware.RoutesMiddleware(self._dispatch, self._mapper)
def __call__(self, req):
return self._router
def _dispatch(req):
match = req.environ['wsgiorg.routing_args'][1]
if not match:
return webob.exc.HTTPNotFound()
app = match['controller']
return app
app = Router()
httpd = make_server('localhost', 8282, app)
httpd.serve_forever()
22行:创建一个mapper
23行:#注册一个路由
28行:创建一个RoutesMiddleware对象,匹配路由,修改环境变量后,调用self._dispatch
- 运行结果